package cn.biplam.back.services.operatorexchange;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import cn.biplam.common.client.DataFilter;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.client.Log;
import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.client.Log.Log_Level;
import cn.biplam.common.interfaces.OperatorExchangeServer;
import cn.biplam.common.paramters.SysName;
import cn.biplam.common.tools.Call;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.sqlresult.SqlResult;

/**
 * Operator交换服务接口实现类
 * @author WangSong 2009-9-22下午03:58:17
 * @version 1.0
 */
public class OperatorExchangeServerImpl extends UnicastRemoteObject implements OperatorExchangeServer{

	private static final long serialVersionUID = -962633219033659110L;
	private Lock mLock=new ReentrantLock();
	private int iCount=0;
	private static KvMap<String, String[]>map;
	private DbResource rt;
	
	/**
	 * 构造方法
	 * @throws RemoteException
	 * @throws ErrorMessage 
	 */
	public OperatorExchangeServerImpl() throws RemoteException, ErrorMessage {
		iCount++;
		map=new KvMap<String, String[]>();
		rt=new DbResource();
	}
	
	/**
	 * 取执行sql结果
	 * @param opId  操作id
	 * @param userId 用户id
	 * @param filter 过滤条件
	 * @param dbResource 数据源
	 * @return 执行sql结果
	 * @throws RemoteException
	 * @throws ErrorMessage
	 */
	public OperatorResult get(String opId, 
							  String userId, 
							  DataFilter filter,
			                  DbResource dbResource) throws RemoteException, ErrorMessage {
		addCount();
		OperatorResult or = null;
		try{
			or = getOperatorResult(opId, userId, filter, dbResource);
		}catch(ErrorMessage e){
			throw e;
		}catch(Exception e){
			throw new ErrorMessage(e,"OperatorExchange Server get failed!");
		}finally{
			reduceCount();
		}
		return or;
	}
	
	/**
	 * 取执行sql结果
	 * @param opId  操作id
	 * @param userId 用户id
	 * @param filter 过滤条件
	 * @param dbResource 数据源
	 * @return 执行sql结果
	 * @throws RemoteException
	 * @throws ErrorMessage
	 */
	private OperatorResult getOperatorResult(String opId, 
			  								 String userId, 
			  								 DataFilter filter,
			  								 DbResource dbResource) throws ErrorMessage{
		/**检查参数是否为空,抛出异常,便于开发阶段发现空值,正式运行后删除该部分代码*/
		if(dbResource==null){
			dbResource=rt;
		}
		if(opId==null){
			throw new ErrorMessage("Param:opId is null");
		}
		if(filter==null){
			throw new ErrorMessage("Param:filter is null");
		}
		if(userId==null){
			Log.write(new ErrorMessage("Param:userId is null at "+opId), Log_Level.Error);
			userId=SysName.SysUser;
		}

		
		/**根据operatorId查询配置表中操作类*/
		String[] classPath = getClassByOPeratorId(opId);
		if(classPath==null || classPath[0]==null){
			throw new ErrorMessage("OperatorExchangeServerImpl error,OperatorId is not found:"+opId);
		}else if(!"1".equals(classPath[1])){
			/**判断模型是否发布*/
			throw new ErrorMessage("OperatorExchangeServerImpl error,OperatorId is not authorized:"+opId);
		}

		Call call = null;
		OperatorResult rs;
		try{
			/**创建操作类的实例*/
			call = new Call(classPath[0]);
			rs=(OperatorResult)call.run("get", opId,userId,filter,dbResource);
		}catch(ErrorMessage e){
			throw e;
		}catch(Exception e){
			throw new ErrorMessage(e,"getOperatorResult failed!");
		}
		return rs;
	}
	
	/**
	 * 根据操作码来查询实现类
	 * @param opId 操作码id
	 * @return 实现类
	 * @throws ErrorMessage 
	 */
	private String[] getClassByOPeratorId(String opId) throws ErrorMessage{
		String[] classInfo=map.getByKey(opId);//查询静态容器
		if(classInfo!=null)
			return classInfo;
		SqlResult sr = new OperatorServiceOpt().getById(opId.substring(0,opId.length()-2));
		if(TOOLS.exist(sr)){
			classInfo=new String[]{sr.get(0,"s_class_path"),sr.get(0,"publish")};
			map.put(opId, classInfo);//放入静态容器
			return classInfo;
		}else{
			throw new ErrorMessage("OperatorId is not found:"+opId);
		}
	}
	
	
	/**服务监控用*/
	public int getCount() throws RemoteException {
		return this.iCount;
	}

	private synchronized void addCount() {
		this.iCount++;
	}

	private synchronized void reduceCount() {
		this.iCount--;
	}

	public void lock() throws RemoteException {
		mLock.lock();
	}

	public boolean trylock() throws RemoteException {
		return mLock.tryLock();
	}

	public void unlock() {
		mLock.unlock();
	}

}
